package pkleczek.bugbrain.laboratory;

import java.util.ArrayList;
import java.util.List;

import android.graphics.Point;

import pkleczek.bugbrain.helpers.Dimension;
import pkleczek.bugbrain.laboratory.elements.CircutElement;
import pkleczek.bugbrain.laboratory.elements.Element;
import pkleczek.bugbrain.laboratory.elements.Synapse;

/**
 * Przechowuje dane obiektów znajdujących się w obszarze roboczym.
 * 
 * @author Pawel Kleczek
 * 
 */
public class Workspace {
	/**
	 * Wymiar obszaru roboczego (w polach).
	 */
	private Dimension dimension;

	private List<Element> elements = new ArrayList<Element>(20);
	private List<Synapse> synapses = new ArrayList<Synapse>(30);

	public Workspace(Dimension dimension) {
		this.dimension = new Dimension(dimension);
	}

	/**
	 * Dodaje element nowy element należący do zadanej klasy na płytce o
	 * podanych współrzędnych.
	 * 
	 * 
	 * @param elemClass
	 * @param pos
	 * @return utworzony element (lub <code>null</code> jeśli nie da się wstawić
	 *         elementu np. z powodu zajętości)
	 */
	public Element addElement(Class<? extends Element> elemClass, Point pos) {

		Element elem = null;
		try {
			elem = elemClass.newInstance();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// Sprawdź pod kątem dostępności wszystkie pola, które zostaną zajęte
		// przez element.
		Point p = new Point();
		for (int dx = -elem.getSize() / 2; dx < elem.getSize() / 2; dx++) {
			for (int dy = -elem.getSize() / 2; dy < elem.getSize() / 2; dy++) {
				p.set(pos.x + dx, pos.y + dy);
				if (!isWithinWorkspace(p))
					return null;

				List<Object> items = getClickedItems(p);
				for (Object o : items) {
					if (CircutElement.class.isAssignableFrom(o.getClass()))
						return null;
				}
			}
		}

		elem.setPosition(pos);

		elements.add(elem);
		return elem;
	}
	
	public void addSynapse(Synapse s) {
		synapses.add(s);
	}

	/**
	 * Zwraca wszystkie elementy i synapsy, które nachodzą na pole o zadanych
	 * współrzędnych.
	 * 
	 * @param p
	 * @return
	 */
	public List<Object> getClickedItems(Point p) {
		List<Object> items = new ArrayList<Object>();

		for (Element e : elements) {
			if (e.contains(p))
				items.add(e);
		}

		// TODO : sprawdzanie dla synaps

		return items;
	}

	/**
	 * Sprawdza, czy dane pole leży w obrębie obszaru roboczego.
	 * 
	 * @param p
	 * @return
	 */
	private boolean isWithinWorkspace(Point p) {
		return (p.x >= 0 && p.x < dimension.width && p.y >= 0 && p.y < dimension.height);
	}

	public List<Element> getElements() {
		return elements;
	}
	
	public List<Synapse> getSynapses() {
		return synapses;
	}
	
	public void clear() {
		elements.clear();
		synapses.clear();
	}
}
